﻿using Loyalty.Application;
using System.Data;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Linq.Expressions;
using System.Text;

namespace Loyalty.Infrastructure.EntityFramework.Poco
{
    public static class DbSetHelper
    {
        public static List<T> GetAllValues<T>(this IDbSet<T> sender, Expression<Func<T, bool>> pre, IUnitOfWork uow) where T : class
        {
            var item = uow.GetChangeTracker().Entries().Where(x => x.State == EntityState.Added && x.Entity is T).ToList();
            var ret = sender.Where(pre).ToList();

            var se = item.Select(en => (T)(en.Entity)).AsQueryable().Where(pre).ToList();

            ret.AddRange(se);


            var itemEdit = uow.GetChangeTracker().Entries().Where(x => x.State == EntityState.Modified && x.Entity is T).ToList();
            foreach (var entity in itemEdit)
            {
                if (ret.AsQueryable().Where("Id=" + entity.Entity.GetType().GetProperty("Id").GetValue(entity.Entity, null).ToString()).FirstOrDefault() != null)
                {
                    var retitt = ret.AsQueryable().Where("Id=" + entity.Entity.GetType().GetProperty("Id").GetValue(entity.Entity, null).ToString()).FirstOrDefault();
                    ret.Remove(retitt);
                    ret.Add((T)(entity.Entity));
                }
            }

            var itemDelete = uow.GetChangeTracker().Entries().Where(x => x.State == EntityState.Deleted && x.Entity is T).ToList();
            foreach (var entity in itemDelete)
            {
                if (
                    ret.AsQueryable()
                       .Where("Id=" + entity.Entity.GetType().GetProperty("Id").GetValue(entity.Entity, null).ToString())
                       .FirstOrDefault() != null)
                {

                    var ex =
                        ret.AsQueryable()
                           .Where("Id=" +
                                  entity.Entity.GetType().GetProperty("Id").GetValue(entity.Entity, null).ToString())
                           .FirstOrDefault();
                    ret.Remove(ex);
                }
            }



            return ret;
        }

        public static ErrorExeptionsResult<T> RemoveAll<T>(this IDbSet<T> sender, Expression<Func<T, bool>> pre) where T : class
        {
            ErrorExeptionsResult<T> ret = new ErrorExeptionsResult<T>();
            var item = sender.Where(pre).ToList();
            try
            {
                foreach (var t in item)
                    sender.Remove(t);
            }
            catch (Exception ex)
            {
                ret.RequestState = RequestStates.Fail;
                ret.ErrorMessage = ex.Message;
            }
            return ret;
        }

        public static void Update<T>(this IDbSet<T> sender, T entity, IUnitOfWork uow) where T : class
        {
            sender.Attach(entity);
            uow.Entry(entity).State = EntityState.Modified;
        }
        public static void Delete<T>(this IDbSet<T> sender, T entity) where T : class
        {
            sender.Remove(entity);
        }
        public static void Delete<T>(this IDbSet<T> sender, Expression<Func<T, bool>> where) where T : class
        {
            IEnumerable<T> objects = sender.Where<T>(where).AsEnumerable();
            foreach (T obj in objects)
                sender.Remove(obj);
        }

    }
}
